                     Locksmith 6.0 Docs - Part 2
                                  by
                                Mr. Wiz

Program Counter Swap:
     The "PCSW" area of the window is the "program counter swap" control area.  4 address pairs can be specified here.  If the PC equals the first value of the pair, the PC is immediately set to the second value, and execution continues.  This is useful in eliminating slow timing loops, which are unnecessary in the simulator.  Initially 3 pairs of PCSW values are given:
         FCA8 FCB3 - nullifies monitor wait routine
         BA00 BA10 - nullifies DOS 3.3 seek delay routine
         BD9E BDAB - nullifies DOS 3.3 motor-on wait routine

Program Counter Trace Table:
     The bottom 8 lines of the window contain the PC trace table.  The last 64 values of the program counter are kept here, so that whn the simulator is halted, a history of the last 64 instructions can be examined.

Program Halts:
     A program running under control of the simulator halts and the simulator enters idle mode whenever one of the following conditions are met:

          The stop key is pressed.

          An invalid 6502 or 65C02 opcode is encountered. ??? will
          be displayed where the opcode should be.

          A JSR or RTS instruction is fetched while running in "T"
          (trace) mode.

          A read or write to the device select addresses of a slot marked
          as "I" (invalid) in the slot table.

          A compare stop occurs for PC, MR, or MW while running.

          An attempt is made to write to the floppy disk.

          An attempt is made to reference certain I/O addresses.
          Among these are $C060 and $C068 for either read or write.

Internal Operational Notes:
     A few notes about the internal operation of the boot tracer/simulator/debugger:
     Floppy disk reading is simulated by reading an entire track of nibbles and passing them one at a time to the simulated program requesting them.  Each time the simulated program requests a nibble, the next nibble in the buffer is returned.  The simulated program never has to wait for a nibble by polling the high-order bit of the disk register.  Because of this, framing bit timing is not preserved.  In additon, the track is not synchronized to any other track upon reading.  Floppy disk writing is not supported.
     When reading a floppy disk, the simulator maintains the nibbles of the most current track on the simulator's system RAM card.  This track image is valid until either the slot or drive number is changed or reselected, or the read/write head is stepped to a different track.  Only if the current track image is invalid will the real floppy disk be read again.  Therefore, if the user performs a CATALOG operation while under control of the simulator and then changes the disk and performs another CATALOG operation, the catalog information from the first disk will still be displayed because the catalog did not cause the head to change tracks and invalidate the track buffer.  To manually invalidate the buffer, change the slot spcification to 'I' and back to 'D' while the simulator is running.
     The simulator has code for "sector-assist" built in.  This means that when the simulated program requests a nibble followed immediately by testing for disk register ready and compare for $D5, the simulator immediately finds the next $D5 in the track buffer and returns it to the simulated program, instead of requiring the program to ignore each nibble until the value $D5 is found.
     The paddle I/O addresses ($C064-$C067 and $C06C-$C06F) are correctly simulated if the code that accesss the I/O addesses is similar to the monitor routine at $FB1E ($PREAD).  If the reference is not similar, idle mode will be entered.

     One final note about ABT.  It is not fast!  A typical disk trace took over 40 minutes just to simulate a typical 30 second game boot.  However, the results and information gained were outstanding.  Be patient!


LOCKSMITH PROGRAMMING LANGUAGE:
------------------------------
     Locksmith Programming Language (LPL) is a user tool to specify how LS is to perform certain functions.  With it, you can set up certain procedures to backup difficult to copy disks, search for information, repair damaged disks, etc.  LPL commands, or statements, are collected into a file that can be entered from the keyboard and saved to a parm disk.

The .I (Include) Command:
     Files are saved under their own names.  For example, if a file called "BRODBUND" exists on a parm disk and it contains LPL statements you wish to use in the current file, use the following statement in your LPL file:
          .I BRODBUND
The .I must appear as the first characters on the line, followed by a space and the name of the file.  To include part of a file, specify the starting and ending line numbers:
          .I TESTFILE,4-1F
would include only lines 4 through 1F of the TESTFILE.  There is no limit to the number of .I statements you can use, except that the total number of lines cannot exceed $FF.
     Each line in an LPL file is given a line number (in hex and inverse).  Line numbers are really unimportant except for reference purposes.  Lines cannot exceed 38 characters in length.  The following is an example of an LPL line:
          FIND D5 AA 96
This is an example of a single LPL statement.  Multiple statements are allowed separated by a colon (:). Example:
          SLOT 6 : IN.DRIVE 1 : OUT.DRIVE 2
Spaces before and after colons are not necessary.  If a line will exceed 38 characters it can be continued on the next line by coding a "-" as the last character on the line:
          DEPOSIT (DF) (F4) (DF) (D4) (FF) -
          D5 AA 96 AA AA
You may insert remarks or comments if proceeded by an asterisk (*).  Examples:
          * SET SLOT NUMBER : SLOT 6
          SLOT 6 : * SET SLOT NUMBER
Both lines are equal, valid statements after a colon will be acted upon.

LPL Statements:
     LPL statements consist of "tokens" which can be thought of as words in a sentence.  Tokens are separated by blanks.  The first token used in a statement determines the type of the statement.  A token can represent variable names or parameter names, a constant, or a processing routine name.  Statements can be grouped into the following categories:
          Comment or blank line
          Statement label
          Assignment statement
          Processing
Any statement may have a statement label preceding it.  Statement labels are optional and are used for branching within the LPL file with the GOTO statement.  A statement label begins with the keyword "LABEL", and is followed by a name.  Label names can be of any length, and are any sequence of alphanumeric characters or any period, with the first character alphabetic.  Examples:
          LABEL READ.TRACK.AGAIN :
          GOTO READ.TRACK.AGAIN

          LABEL A2:ERROR:PRT "LENGTH ERROR"
          GOTO A2.ERROR

Types of Constants:
     Several types of constants are used in LPL.  They are described herewith.
     Single byte constant (hex):
          D5
          6
          00
          (FF) single bytes in parentheses indicate self-sync

     Multiple byte constant (hex:
          (FF) D5 AA 96
          00 10 20 30 40 50 60 70 80

     Double byte constant (hex):
          1A70 Double byte constants usually represent addresses or lengths.

     Track value constant (hex):
          12.5
          1A.75
          11.0
          0.
          Track value constants contain a decimal point.

     Single byte character constant:
          "X"
          'X' Note that either single or double quotes are used.

     Multiple byte character constants:
          "DON'T FORGET TO COVER NOTCH."
          If a quote is to appear in the constant, use the other
          quote to delimit the string.

     Multiple byte constants can consist of a mix of hex and ASCII:
          89 'GRD' 8D

     Special constants:
          ? - represents a "don't care" value when used in a search pattern.

     Flag constants:
          YES
          NO
          ON
          OFF
          These are equivalent to 0-FF, but are preferred because of their
          readability.

Types of Variables:
     Variable names within LPL usually have a specified use for each name, although some general purpose names have been provided for the user.  Several types of variable names are provided within LPL:
     Single byte variable:
          SLOT
          IN.DRIVE
          OUT.DRIVE

     Multiple byte pattern/string variables:
          GR.CHARS
          PAT1
          SYNC.PAT
          Pattern/string variables are variable length, and have a one byte
          length as the first byte of a variable.  Although pattern/string
          variables have a variable lenght, each is allowed a maximum length
          of 15 (decimal).

     Multiple byte variable:
          RD.NIB.TRANS
          SEC.TRANS
          SELECT.TAB
          These variables refer to multiple-byte areas of memory of fixed
          length, such as lookup tables.

If you have a need to refer to a byte within a multiple byte variable, you can code a plus sign followed by the displacement into the table:
        NIB.TRANS +2F

     Double byte pointer variable:
        START
        END
        LEN
        CURSOR
        PTR.W
        PTR.X
        Double byte pointer variables can also represent length.

     Track variable:
        BEGIN.TRK
        END.TRK
        INCR.TRK
        SYNC.TRK
        Track variables can represent integral track values or 1/4,
        1/2, or 3/4 tracks.

     Flag variable:
        SYNC
        COUNT
        SHOW.ADDR
        Flag variables are single byte variables that contain a flag of
        YES/NO, ON/OFF, or FF/0 and act as switches which can be set
        and tested.  Values other than these may have unpredictable results.

The Assignment Statement:
     Used to assign a value to a variable.  The variable can be assigned the value of a constant or another variable.  The variable and the constant to which it is assigned must be of the same type.  For example, a pointer variable can only be assigned to another pointer variable.  Examples:
        START CURSOR - Set the variable START (start of track data)
        to CURSOR (current cursor locaton).

        CURSOR 2040 - Set variable of CURSOR to point to 2040.

        SLOT 6 - Set one-byte var SLOT to value of 6.

        BEGIN.TRK 12.5 - Set track var BEGIN.TRK to value of 12.5

        COUNT YES - Set flag var to flag value of yes.

        PAT4 D5 AA 96
        PAT4 PAT7 - Both examples are valid.

        GR.CHARS 89 'GRD' - Set string var GR.CHARS to 4 byte string
        consisting of hex 89 (CTRL-I) followed by ASCII 'GRD'.

        DF.HDR3 B4 : AF.HDR3 DD - Set the third data field header byte to
        B4 (normally AD) and third address header byte to DD.

        AF.TRL1.TEST IGNORE.TRL
        AF.TRL2.TEST IGNORE.TRL
        DF.TRL1.TEST IGNORE.TRL
        DF.TRL2.TEST IGNORE.TRL - Assignment statements patch RWTS to
        ignore the trailer nibbles of the address and data fields.

        AF.TRL1.TEST NORM.TRL1
        DF.TRL1.TEST NORM.TRL1 - Patch RWTS back to normal trailer nibble
        checking.

        AF.CSUM.TEST IGNORE.CSUM
        DF.CSUM.TEST IGNORE.CSUM
        AF.CSUM.TEST NORM.AF.CSUM
        DF.CSUM.TEST NORM.DF.CSUM - Used to patch RWTS to ignore or to use
        address field and data field checksum.

        AF.HDR1 D5
        AF.HDR2 AA
        AF.HDR3 96
        AF.TRL1 DE
        AF.TRL1 AA
        DF.HDR1 D5
        DF.HDR2 AA
        DF.HDR3 AD
        DF.TRL1 DE
        DF.TRL1 AA - Set default header and trailer values for address
        fields and data fields used for reading.


        DF.HDR1.WRT D5
        DF.HDR2.WRT AA
        DF.HDR3.WRT DD
        DF.TRL1.WRT DE
        DF.TRL2.WRT AA
        DF.CSUM.SEED.WRT 00 - Set header and trailer nibbles to be used
        when writing a data field. The last statement sets the seed to
        be used for the calculation of the checksum for writing the data
        field.

Processing Routines:
     LPL processing routines (algorithms in earlier versions of LS) are routines that the user can invoke on demand using LPL.  Some of the routines are complex and are driven by many variables, while others are simple and operate using only one or two variables.  Some routines use parameters consisting of constants or pointers passed to them and some accept no parameters at all.  The valid syntax of each processing routine is described in an addendum, but we will describe some of the routines here and give some examples of their use.  The Parm disk has excellent examples of routines.

        ABORT "DATA NOT FOUND" - Abort current operation and return to LS
        main menu.

        PAUSE "ENTER 1,2 OR 3:" - After a keypress, the value of the key
        is placed in the single-byte variable KEY.IN

        PRT "DISK MUST BE WRITE/ENABLED" - Prints message on screen.
        If last character is blank, cursor remains on same line.

        SHOW SLOT - Print value of variable named slot. If flag variable
        SHOW.ADDR is YES or NO, the address of the variable SLOT is also
        printed.

        GOTO READ.AGAIN - Branches to lable READ.AGAIN elsewhere in LPL.

        FIND D5 AA 96 - Search from current cursor position until END
        pointer, searching for D5 AA 96.

        FIND PAT4 - Same as previous example, except search for the contents
        of string var PAT4.

        ERROR '5' - Causes the character '5' to be placed in the current
        track of the status display area.

        PAT4 D4 DD FF
        PAT5 D5 AA 96
        CHANGE PAT4 PAT5 - Changes all occurences of first string to
        second string for entire range of START to END.

        ERASE - Causes track to be erased on the output drive.

        FORWARD TRK.LEN
        BACK TRK.LEN - Cause CURSOR to be moved forward or back by the
        length determined by variable TRK.LEN. These routines can also
        be coded with a 2-byte constant: FORWARD 024E or BACK 0042

        CODE AD CUR.TRK 0A 0A 0A 0A 60 - CODE processing routine is provided
        for 6502 M/L programmer.  Parms supplied are decoded, placed in a 
        contiguous area of memory, and given control with a JSR instruction.

        PRT "ASCII TEXT TO PRINT" - The PRT routine prints data on screen.
        If last byte is blank, no new line is started. Example:
        PRT "TRACK INCREMENT IS " : SHOW INCR.TRK

Some processing routines function slightly differently depending on whether in "nibble-mode" or "byte-mode".  If the last read or write command was NREAD or NWRITE, the nibble-mode is used.  If last read or write is SREAD, SWRITE, TREAD or TWRITE then byte-mode is used.

The routines which function differently depending on whether in nibble or byte mode are FIND, VER, and CHANGE.

In nibble mode, a zero value in the pattern specified acts as a "don't care" value.  It can be either coded as "?" or "0".

In byte mode (used when reading or writing sectors), the zero value in a pattern is significant.  Example:

        NREAD : FIND D5 00 96

Performs a nibble-read of the current track, and places the CURSOR on the first occurence of a D5 value, followed by any value, followed by a 96 value.

The following processing routines accept either string vars or multiple byte constants:

        FIND
        VER
        REP
        DEPOSIT

The nibble or byte mode can be changed manually by setting the flag variable BYTE.MODE to YES if byte mode is desired, or NO if nibble mode is desired.

Track Procedures:
     A track procedure is a sequence of LPL statements that are to be executed for each track that is being copied.  The track procedure is defined with the BEGIN.PROC and END.PROC statements.  The procedure is then later invoked for each track to be processed, by the processing routine which will invoke the track procedure.  There is currently only one procedure to invoke this processing, the COPY procedure.  The "current" procedure is the last one to be defined.  If no procedure is defined, then the default LPL procedure will be used.  For example:
         BEGIN.PROC
           ...
            ... track procedure A
           ...
         END.PROC

         COPY 12 18 2


         BEGIN.PROC
           ...
            ... track procedure B
           ...
         END.PROC

         COPY 1 9 2
         COPY 13 19 2

In this example, the first 2 copy procedures will use track procedure A, the second two will use procedure B.

     The LPL statements within the track procedure can be used to process a track in one of two modes.  Either in nibble-mode or sector-mode.  Nibble processing routines are NREAD, NWRITE, NVERIFY, whcih process a track in the form of nibbles.  Sector-mode processing routines are TREAD, TWRITE, TVERIFY which process a track in the form of 16 separate sectors.
     The format of a COPY command is: COPY <begin track> <end track> <track increment>.  The values are stored in the variables BEGIN.TRK, END.TRK, and INCR.TRK.
     If tracks are to be synchronized or nibble counting is to be used, set track variables SYNC or COUNT to YES.  The SYNC and COUNT keywords are not set to YES as in LS version 5.0.

LPL Error Codes:
     During execution of the LPL program, some errors may be encountered which cannot be checked for during syntax checking.  If an error is found, processing stops and the following message is displayed on the screen:
         LPL CODE ABORTED

          ERROR CODE xx
where xx is one of the following:

01 GOTO statement encountered without finding the matching LABEL statement.

02 BEGIN.PROC statement encountered while already within a track procedure.

03 END.PROC statement encountered while already outside a track procedure.

04 COPY statement encountered within a track procedure. The COPY statement invokes a track procedure and cannot occur within one.

05 USE.DEFAULT.PROC encountered while within a track procedure.


Data Field Nibble Encoding Table:
--------------------------------
     The following translate table is used for calculating data field checksums.  It is described in the chapter on the disk editor describing the 'D' command.

         00:96    01:97    02:9A    03:9B
         04:9D    05:9E    06:9F    07:A6
         08:A7    09:AB    0A:AC    0B:AD
         0C:AE    0D:AF    0E:B2    0F:B3
         10:B4    11:B5    12:B6    13:B7
         14:B9    15:BA    16:BB    17:BC
         18:BD    19:BE    1A:BF    1B:CB
         1C:CD    1D:CE    1E:CF    1F:D3
         20:D6    21:D7    22:D9    23:DA
         24:DB    25:DC    26:DD    27:DE
         28:DF    29:E5    2A:E6    2B:E7
         2C:E9    2D:EA    2E:EB    2F:EC
         30:ED    31:EE    32:EF    33:F2
         34:F3    35:F4    36:F5    37:F6
         38:F7    39:F9    3A:FA    3B:FB
         3C:FC    3D:FD    3E:FE    3F:FF

END OF PART 2 OF 2 PARTS..............................................